function [config_binary_new, owner_total_profit, flag_iter]...
    = prod_equi_swap(...    
    config_binary_init, binary_prod, ...
    fixed_prod_ind_id, fixed_prod_entry_m, fixed2, fixed2_entry, ...
    prod_sim_fc, fc_first, nfc, ...
    firm_seq, sim_pcoeff,  ...
    max_iter_count, setup, ...
    prod_id_by_owner, brewer_name_by_owner, ...
    para_nonlinear, randomdraw, ...
    rand_income, income_norm, starting_point_option, display_setup)
%PURPOSE: find the product-choice equilibrium

n_owner = size(config_binary_init,1);

% delete firm who has no potential products
for no = 1:n_owner
    if isempty(cell2mat(config_binary_init(no,:)'))
        firm_seq(firm_seq == no) = [];
    end
end

config_binary_start0 = config_binary_init;

if isequal(setup.BR_method, 'one_product') % for each firm, find best-response using one-product-swamp
    config_changed = true;
    iter_count_Jacobi = 0;    
    
    while config_changed && iter_count_Jacobi<max_iter_count
        d_profit_all = -1*ones(length(firm_seq), 1);        
        config_binary_iter = config_binary_start0; 

        for n_iter = 1:length(firm_seq)
            n = firm_seq(n_iter);

            %(1) construct starting point for searching for firm n's best response 
            config_binary_n_start = config_binary_iter;            

            if isequal(starting_point_option, 'full')
                config_binary_n_start{n} = true(size(config_binary_n_start{n}));                
            elseif isequal(starting_point_option, 'null')                
                config_binary_n_start{n} = false(size(config_binary_n_start{n}));                
            end
            
            config_binary_n_start{n}(fixed2{n}) = fixed2_entry{n};

            owner_var_profit_start = ...
                prod_config_profit(binary_prod, ...
                fixed_prod_ind_id, fixed_prod_entry_m, config_binary_n_start, prod_id_by_owner, ...
                sim_pcoeff, setup, ...
                para_nonlinear, randomdraw, ...
                rand_income, income_norm);

            fc_start = compute_fc([], config_binary_n_start, ...
                brewer_name_by_owner, [],[],[], fc_first, prod_sim_fc, nfc);

            owner_total_profit_start = owner_var_profit_start(n) - fc_start(n);
            
            config_considered = cell2mat(config_binary_n_start(:));

            %(2) loop over potential products to record the one-product deviating profit 
            config_binary_n_new = config_binary_n_start;
            owner_total_profit_n_new = owner_total_profit_start;
            n_prod_n = length(config_binary_n_start{n});
            
            d_profit = 1;
            iter_count = 0;

            while d_profit>0
                config_binary_n_prev = config_binary_n_new;
                owner_total_profit_n_prev = owner_total_profit_n_new;
                                                
                owner_total_profit_dev = nan(n_prod_n, 1);  % deviating profit

                for j = 1 : n_prod_n                    
                    if ~fixed2{n}(j)                        
                        config_binary_nj = config_binary_n_prev;                        
                        config_binary_nj{n}(j) = 1 - config_binary_nj{n}(j);                        
                        if ~ismember(cell2mat(config_binary_nj(:))', config_considered', 'rows')
                            owner_total_profit_nj = ...
                                prod_config_profit(binary_prod, ...
                                fixed_prod_ind_id, fixed_prod_entry_m, config_binary_nj, prod_id_by_owner, ...
                                sim_pcoeff, setup, ...
                                para_nonlinear, randomdraw,  ...
                                rand_income, income_norm);
                                   
                            fc_nj = compute_fc([], config_binary_nj, ...
                                brewer_name_by_owner, [],[],[], fc_first, prod_sim_fc, nfc);
                            
                            owner_total_profit_dev(j) = owner_total_profit_nj(n) - fc_nj(n);
                            
                            config_considered = [config_considered, cell2mat(config_binary_nj(:))];
                        end
                    end                    
                end
                
                [max_profit, ind_max] = max(owner_total_profit_dev);
                
                d_profit = max_profit - owner_total_profit_n_prev;
                
                if isnan(d_profit) || d_profit<0                    
                   d_profit = -1;    
                else                    
                    config_binary_n_new = config_binary_n_prev;                    
                    config_binary_n_new{n}(ind_max) = 1 - config_binary_n_new{n}(ind_max);                
                    owner_total_profit_n_new = max_profit;
                end
                
                iter_count = iter_count + 1;
                d_profit_all(n_iter) = d_profit;
            end
            
            config_binary_iter = config_binary_n_new;            
        end
        
        config_binary_new = config_binary_iter;

        iter_count_Jacobi = iter_count_Jacobi + 1;
        config_changed = ~isequal(config_binary_new, config_binary_start0);
        
        % display
        if display_setup.display
            fprintf(1, 'np=%1.0f, mktid=%1.0f, fc draw=%1.0f, Jacobi iter %1.0f: done\n', display_setup.np, display_setup.mktid, display_setup.nfc_cf, iter_count_Jacobi);
        
            for no = 1 : n_owner            
                n_prod_diff = sum(config_binary_start0{no}) - sum(config_binary_new{no});
                
                if n_prod_diff>0
                    fprintf(1, 'np=%1.0f, mktid=%1.0f, fc draw=%1.0f, Jacobi iter %1.0f: owner %1.0f drops %1.0f products\n', display_setup.np, display_setup.mktid, display_setup.nfc_cf, iter_count_Jacobi, no, n_prod_diff);
                elseif n_prod_diff<0
                    fprintf(1, 'np=%1.0f, mktid=%1.0f, fc draw=%1.0f, Jacobi iter %1.0f: owner %1.0f adds %1.0f products\n', display_setup.np, display_setup.mktid, display_setup.nfc_cf, iter_count_Jacobi, no, -n_prod_diff);
                end                        
            end
        end
        % update
        config_binary_start0 = config_binary_new;        
    end
    
    d_profit_max = max(d_profit_all);

else
    error('to be written');
    
end


owner_var_profit = ...
    prod_config_profit(binary_prod, ...
    fixed_prod_ind_id, fixed_prod_entry_m, config_binary_new, prod_id_by_owner, ...
    sim_pcoeff, setup, ...
    para_nonlinear, randomdraw, ...
    rand_income, income_norm);

fc = compute_fc([], config_binary_new, ...
    brewer_name_by_owner, [], [], [], fc_first, prod_sim_fc, nfc);

owner_total_profit = owner_var_profit - fc;

if d_profit_max>0
    flag_iter = -1;
elseif d_profit_max==0
    flag_iter = 0;
else
    flag_iter = 1;
end

if iter_count_Jacobi>=max_iter_count-1
    flag_iter = -2;
end
